package com.gitee.cui.client.client;

import com.gitee.cui.client.config.SystemConfig;
import com.gitee.cui.client.handler.ExceptionHandler;
import com.gitee.cui.client.handler.LoginResponseHandler;
import com.gitee.cui.common.common.codec.SimpleProtobufDecoder;
import com.gitee.cui.common.common.codec.SimpleProtobufEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * 聊天Netty实现客户端
 * @author cuiqingqiang
 * @version 1.0
 * @date 2021/10/27 15:53
 **/
@Slf4j
@Data
@Service
public class ChatNettyClient {

    @Autowired
    private LoginResponseHandler loginResponseHandler;

    @Autowired
    private ExceptionHandler exceptionHandler;

    @Autowired
    private SystemConfig systemConfig;

    @Value("${chat.server.ip}")
    private String host;

    @Value("${chat.server.port}")
    private int port;

    private Bootstrap bootstrap;

    private EventLoopGroup worker;

    private GenericFutureListener<ChannelFuture> listener;

    public ChatNettyClient () {
        worker = new NioEventLoopGroup();
    }

    /**
     * 连接服务端
     */
    public void doConnect() {
        bootstrap = new Bootstrap();
        bootstrap.group(worker);
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
        bootstrap.remoteAddress(host, port);
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast("decoder", new SimpleProtobufDecoder());
                ch.pipeline().addLast("encoder", new SimpleProtobufEncoder());
                ch.pipeline().addLast(loginResponseHandler);
                ch.pipeline().addLast(exceptionHandler);
            }
        });
        ChannelFuture future = bootstrap.connect();
        future.addListener(listener);
    }

    /**
     * 关闭资源
     */
    public void doClose() {
        worker.shutdownGracefully();
    }
}
